package com.miaopasi.securitydemo.config.security;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.*;

/**
 * Token 生成校验工具类
 *
 * @author lixin
 */
public class JwtTokenUtil {
    /*** 密码算法 **/
    private final static SignatureAlgorithm ALG = SignatureAlgorithm.HS512;
    /*** 秘钥 **/
    private final static String SECRET_KEY = Base64.encode("123456");
    /*** 签发人 **/
    private final static String ISS = "miaopasi.cn";
    /*** 默认过期时间（秒） **/
    private final static Integer DEFAULT_TIMEOUT_SECOND = 60;

    /**
     * <p>方法名称：创建一个 token 字符串.</p>
     * <p>详细描述：.</p>
     * <p>创建时间：2020-06-11 23:10:47</p>
     * <p>创建作者：李兴武</p>
     * <p>修改记录：</p>
     *
     * @param subject 签发人主体
     * @return the string
     */
    public static String createToken(String subject) {
        return createToken(subject, null, null, null);
    }

    /**
     * <p>方法名称：创建一个 token 字符串.</p>
     * <p>详细描述：.</p>
     * <p>创建时间：2020-06-11 23:10:47</p>
     * <p>创建作者：李兴武</p>
     * <p>修改记录：</p>
     *
     * @param subject    签发人主体
     * @param expiration 过期时间（不传选择默认）
     * @return the string
     */
    public static String createToken(String subject, Integer expiration) {
        return createToken(subject, expiration, null, null);
    }

    /**
     * <p>方法名称：创建一个 token 字符串.</p>
     * <p>详细描述：.</p>
     * <p>创建时间：2020-06-11 23:10:47</p>
     * <p>创建作者：李兴武</p>
     * <p>修改记录：</p>
     *
     * @param subject    签发人主体
     * @param issuer     签发人，为空使用默认的
     * @param expiration 过期时间（不传选择默认）
     * @return the string
     */
    public static String createToken(String subject, Integer expiration, String issuer) {
        return createToken(subject, expiration, issuer, null);
    }

    /**
     * <p>方法名称：创建一个 token 字符串.</p>
     * <p>详细描述：.</p>
     * <p>创建时间：2020-06-11 23:10:47</p>
     * <p>创建作者：李兴武</p>
     * <p>修改记录：</p>
     *
     * @param subject    签发人主体
     * @param issuer     签发人，为空使用默认的
     * @param expiration 过期时间（不传选择默认）
     * @param claims     自定义属性（可不传）
     * @return the string
     */
    public static String createToken(String subject, Integer expiration, String issuer, Claims claims) {
        // 获取当前时间
        DateTime now = DateTime.now();
        // 生成token
        return Jwts.builder()
                // 签名算法以及密匙
                .signWith(ALG, SECRET_KEY)
                // 自定义属性
                .setClaims(claims)
                // 主题：代表这个JWT的主体，
                // 即它的所有人，这个是一个json格式的字符串，
                // 可以存放什么userid，roldid之类的，作为什么用户的唯一标志。
                .setSubject(subject)
                // 签发人
                .setIssuer(StrUtil.isBlank(issuer) ? ISS : issuer)
                // 签发时间
                .setIssuedAt(now)
                // 过期时间(秒)
                .setExpiration(now.offset(DateField.SECOND, expiration == null ? DEFAULT_TIMEOUT_SECOND : expiration))
                .compact();
    }

    /**
     * <p>方法名称：解析token字符串为ClaimsJws.</p>
     * <p>详细描述：.</p>
     * <p>创建时间：2020-06-11 23:27:15</p>
     * <p>创建作者：李兴武</p>
     * <p>修改记录：</p>
     *
     * @param token 被解析token字符串
     * @return the claims
     */
    public static Claims parserToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * <p>方法名称：在token字符串中获取主体.</p>
     * <p>详细描述：.</p>
     * <p>创建时间：2020-06-11 23:31:39</p>
     * <p>创建作者：李兴武</p>
     * <p>修改记录：</p>
     *
     * @param token 被解析token字符串
     * @return the string
     */
    public static String tokenGetSubject(String token) {
        return parserToken(token).getSubject();
    }

    /**
     * <p>方法名称：验证token是否在有效期内.</p>
     * <p>详细描述：.</p>
     * <p>创建时间：2020-06-11 23:37:28</p>
     * <p>创建作者：李兴武</p>
     * <p>修改记录：</p>
     *
     * @param token 被解析token字符串
     * @return the boolean
     */
    public static boolean isExpiration(String token) {
        try {
            return parserToken(token).getExpiration().before(DateTime.now());
        } catch (ExpiredJwtException exception) {
            return true;
        }

    }

    public static void main(String[] args) {
        //String token = createToken("1");
        //Console.log(token);
        String token = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwiaXNzIjoibWlhb3Bhc2kuY24iLCJpYXQiOjE1OTE4OTA5MDgsImV4cCI6MTU5MTg5MDk2OH0.W5nN8KRNJvLMbQlISMAy7KQlPG5OdXYcgk0Axko425dgbGD22oFbD2TBA2I5wRv9W2Ca74hfB35zsNWu9YSA3A";

        //Claims claims = parserToken(token);
        //Console.log(claims);

        String subject = tokenGetSubject(token);
        Console.log(subject);

        // boolean expiration = isExpiration(token);
        // Console.log(expiration);
    }

}
